package indi.yangshenhui.tool;

import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class SecureUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(SecureUtil.class);

	private SecureUtil() {
	}

	/**
	 * 把字节数组转成16进位制数
	 * 
	 * @param bytes
	 * @return
	 */
	public static String bytes2Hex(byte[] bytes) {
		StringBuilder md5str = new StringBuilder();
		// 把数组每一字节换成16进制连成md5字符串
		int digital = 0;
		for (int i = 0; i < bytes.length; i++) {
			digital = bytes[i];
			if (digital < 0) {
				digital += 256;
			}
			if (digital < 16) {
				md5str.append("0");
			}
			md5str.append(Integer.toHexString(digital));
		}
		// toUpperCase方法返回一个字符串,该字符串中的所有字母都被转化为大写字母
		return md5str.toString().toUpperCase();
	}

	/**
	 * 把字节数组转换成md5
	 * 
	 * @param bytes
	 * @return
	 */
	public static String bytes2MD5(byte[] bytes) {
		String md5str = "";
		try {
			// 创建一个提供信息摘要算法的对象,初始化为md5算法对象
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算后获得字节数组
			byte[] temp = md.digest(bytes);
			// 把数组每一字节换成16进制连成md5字符串
			md5str = bytes2Hex(temp);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
		return md5str;
	}

	/**
	 * 把字符串转换成md5
	 * 
	 * @param s
	 * @return
	 */
	public static String string2MD5(String s) {
		return bytes2MD5(s.getBytes());
	}

	/**
	 * 把文件转成md5字符串
	 * 
	 * @param file
	 * @return
	 */
	public static String file2MD5(File file) {
		if (file == null) {
			return null;
		}
		if (file.exists() == false) {
			return null;
		}
		if (file.isFile() == false) {
			return null;
		}
		FileInputStream fis = null;
		try {
			// 创建一个提供信息摘要算法的对象，初始化为md5算法对象
			MessageDigest md = MessageDigest.getInstance("MD5");
			fis = new FileInputStream(file);
			byte[] temp = new byte[1024];
			int l = 0;
			while (true) {
				l = fis.read(temp, 0, temp.length);
				if (l == -1) {
					break;
				}
				// 每次循环读取一定的字节都更新
				md.update(temp, 0, l);
			}
			// 关闭流
			fis.close();
			// 返回md5字符串
			return bytes2Hex(md.digest());
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 获取请求IP getIpAddr
	 * 
	 * @param request
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	// 24字节的密钥
	private static final byte[] keyBytes = { 0x11, 0x22, 0x4F, 0x58, (byte) 0x88, 0x10, 0x40, 0x38, 0x28, 0x25, 0x79,
			0x51, (byte) 0xCB, (byte) 0xDD, 0x55, 0x66, 0x77, 0x29, 0x74, (byte) 0x98, 0x30, 0x40, 0x36, (byte) 0xE2 };
	// 定义 加密算法,可用 DES,DESede,Blowfish
	private static final String Algorithm = "DESede";
	public static char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * MD5加密
	 * 
	 * @param str
	 * @return
	 */
	public static String md5Encrypt(String str, String key) {
		if (str == null || str.trim().length() == 0) {
			return null;
		}

		StringBuffer hexString = new StringBuffer();
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			str = key + str;
			md.update(str.getBytes());
			byte[] hash = md.digest();

			for (int i = 0; i < hash.length; i++) {
				if ((0xFF & hash[i]) < 16) {
					hexString.append("0" + Integer.toHexString(0xFF & hash[i]));
				} else {
					hexString.append(Integer.toHexString(0xFF & hash[i]));
				}
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		return hexString.toString();
	}

	/**
	 * 3des加密
	 * 
	 * @param src
	 * @return
	 */
	public static String des3Crypt(String src) {
		if (src == null || src.trim().length() == 0) {
			return null;
		}

		try {
			// 生成密钥
			SecretKey deskey = new SecretKeySpec(keyBytes, Algorithm);

			// 加密
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			return new String(c1.doFinal(src.getBytes()));
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}

		return null;
	}

	/**
	 * 3des解密
	 * 
	 * @param src
	 * @return
	 */
	public static String des3Decrypt(String src) {
		if (src == null || src.trim().length() == 0) {
			return null;
		}

		try {
			// 生成密钥
			SecretKey deskey = new SecretKeySpec(keyBytes, Algorithm);

			// 解密
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey);
			return new String(c1.doFinal(src.getBytes()));
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}

		return null;
	}

	// 转换成十六进制字符串
	public static String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";

		for (int n = 0; n < b.length; n++) {
			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
			if (n < b.length - 1)
				hs = hs + ":";
		}

		return hs.toUpperCase();
	}

	/**
	 * 
	 * md5返回md5串
	 * 
	 * @param inputText
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public static String md5(String inputText) {
		String encryptText = null;
		if (!StringUtils.isBlank(inputText)) {
			try {
				MessageDigest m = MessageDigest.getInstance("md5");
				m.update(inputText.getBytes("UTF8"));
				encryptText = toHexString(m.digest());
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return encryptText;
	}

	/**
	 * 
	 * toHexString 返回16进制字符串
	 * 
	 * @param b
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public static String toHexString(byte[] b) {
		StringBuilder sb = new StringBuilder(b.length * 2);
		for (int i = 0; i < b.length; i++) {
			sb.append(hexChar[(b[i] & 0xf0) >>> 4]);
			sb.append(hexChar[b[i] & 0x0f]);
		}
		return sb.toString();
	}

	/**
	 * base 64 encode
	 * 
	 * @param bytes
	 *            待编码的byte[]
	 * @return 编码后的base 64 code
	 */
	public static String base64Encode(byte[] bytes) {
		return new BASE64Encoder().encode(bytes);
	}

	/**
	 * base 64 decode
	 * 
	 * @param base64Code
	 *            待解码的base 64 code
	 * @return 解码后的byte[]
	 * @throws Exception
	 */
	public static byte[] base64Decode(String base64Code) throws Exception {
		return new BASE64Decoder().decodeBuffer(base64Code);
	}

	/*
	 * 随机生成国内IP地址
	 */
	public static String getRandomIp() {
		// IP范围
		int[][] range = { { 607649792, 608174079 }, // 36.56.0.0-36.63.255.255
				{ 1038614528, 1039007743 }, // 61.232.0.0-61.237.255.255
				{ 1783627776, 1784676351 }, // 106.80.0.0-106.95.255.255
				{ 2035023872, 2035154943 }, // 121.76.0.0-121.77.255.255
				{ 2078801920, 2079064063 }, // 123.232.0.0-123.235.255.255
				{ -1950089216, -1948778497 }, // 139.196.0.0-139.215.255.255
				{ -1425539072, -1425014785 }, // 171.8.0.0-171.15.255.255
				{ -1236271104, -1235419137 }, // 182.80.0.0-182.92.255.255
				{ -770113536, -768606209 }, // 210.25.0.0-210.47.255.255
				{ -569376768, -564133889 }, // 222.16.0.0-222.95.255.255
		};
		Random rdint = new Random();
		int index = rdint.nextInt(10);
		String ip = num2ip(range[index][0] + new Random().nextInt(range[index][1] - range[index][0]));
		return ip;
	}

	/*
	 * 将十进制转换成IP地址
	 */
	public static String num2ip(int ip) {
		int[] b = new int[4];
		String x = "";
		b[0] = (int) ((ip >> 24) & 0xff);
		b[1] = (int) ((ip >> 16) & 0xff);
		b[2] = (int) ((ip >> 8) & 0xff);
		b[3] = (int) (ip & 0xff);
		x = Integer.toString(b[0]) + "." + Integer.toString(b[1]) + "." + Integer.toString(b[2]) + "."
				+ Integer.toString(b[3]);
		return x;
	}

}
